[프론트엔드 인터뷰]FE-Study 5주차 1회

let, var, const를 사용하여 생성된 변수들의 차이점은 무엇인가요?

var 키워드로 사용하여 선언된 변수는 함수가 생성된 함수나 함수 밖에서 생성된 함수에 전역 오브젝트로 적용됩니다. let과 const는 블록 스코프입니다. 즉, 가장 가까운 중괄호 (function, if-else 블록, for-loop) 내에서만 접근할 수 있습니다.

function foo() {
  var bar = 'bar'
  let baz = 'baz'
  const qux = 'qux'

  console.log(bar) // "bar"
  console.log(baz) // "baz"
  console.log(quz) // "quz"
}

console.log(bar) // ReferenceError: bar is not defined
console.log(baz) // ReferenceError: baz is not defined
console.log(qux) // ReferenceError: qux is not defined
if (true) {
  var bar = 'bar'
  let baz = 'baz'
  const qux = 'qux'
}

// var로 선언된 변수는 함수 스코프의 어디에서나 접근할 수 있습니다.
console.log(bar) // "bar"
// let과 const로 정의된 변수는 정의된 블록 외부에서 접근할 수 없습니다.
console.log(baz) // ReferenceError: baz is not defined
console.log(qux) // ReferenceError: qux is not defined
console.log(foo) // undefined

var foo = 'foo'

console.log(baz) // ReferenceError: can't access lexical declaration 'baz' before initialization

let baz = 'baz'

console.log(bar) // ReferenceError: can't access lexical declaration 'bar' before initialization

const bar = 'bar'

var을 사용하여 변수를 다시 선언해도 에러가 발생하지 않지만, let과 const는 에러를 발생시킵니다.

var foo = 'foo'
var foo = 'bar'
console.log(foo) // "bar"

let baz = 'baz'
let baz = 'qux' // Uncaught SyntaxError: Identifier 'baz' has already been declared

let은 변수의 값을 재할당할 수 있지만, const는 재할당할 수 없다는 점이 다릅니다.

// 괜찮습니다
let foo = 'foo'
foo = 'bar'

// 예외가 발생합니다
const baz = 'baz'
baz = 'qux'

ES6 클래스와 ES5 함수 생성자의 차이점은 무엇인가요?

function Person(name) {
  this.name = name
}

class Person {
  constructor(name) {
    this.name = name
  }
}

생성자 같은경우 거의 유사합니다.

생성자의 주요 차이점은 상속을 사용할 때 발생합니다. Person의 하위 클래스이면서 studentId 필드를 추가로 가지고 있는 Student클래스를 만들고자 한다면, 이것이 우리가 추가로 해야할 일입니다.

// ES5 함수 생성자
function Student(name, studentId) {
  // 슈퍼 클래스의 생성자를 호출하여 슈퍼 클래스에서 상속된 멤버를 초기화합니다.
  Person.call(this, name)

  this.studentId = studentId
}

Student.prototype = Object.create(Person.prototype) // Object.create() 메서드는 지정된 프로토타입 객체 및 속성(property)을 갖는 새 객체를 만듭니다.
Student.prototype.constructor = Student

class Student extends Perosn {
  constructor(name, studentId) {
    super(name)
    this.studentId = studentId
  }
}

ES5에서 상속을 하는게 ES6보다 불편합니다.

새 화살표 => 함수 문법에 대한 사용 예시를 들 수 있나요? 이 새로운 문법은 다른 함수와 어떻게 다른가요?

화살표 함수의 한 가지 분명한 이점은 fucntion 키워드를 사용하지 않고도 함수를 생성하는데 필요한 문법을 단순화 하는 것입니다. 또한, 화살표 함수 내의 this는, this가 함수를 호출하는 객체에 의해 결정되는 일반 함수와는 다르게, this를 사용한 상위 객체를 가르킵니다.

생성자 메서드에 화살표 문법을 사용하면 어떤 이점이 있나요?

생성자 내부에서 화살표 함수를 메소드로 사용하는 주된 장점은, 함수 생성시 this의 값이 설정되고 그 이후에는 변경할 수 없다는 것입니다.

따라서, 생성자가 새로운 객체를 생성하는데 사용될 때, this는 항상 그 객체를 참조할 것입니다.

예를들어, 우리가 인수로 first name을 받고, 그 이름을 console.log로 출력하는 Person 생성자가 있다고 해봅시다. 하나는 일반 함수이고 다른 하나는 화살표 함수일 때,

const Person = function(firstName) {
  this.firstName = firstName
  this.sayName1 = function() {
    console.log(this.firstName)
  }
  this.sayName2 = () => {
    console.log(this.firstName)
  }
}

const john = new Person('John')
const dave = new Person('Dave')

// 일반 함수의 'this'값은 변경할 수 있지만, 화살표 함수는 변경할 수 없습니다.
john.sayName1.call(dave) // Dave (because "this" is now the dave object)
john.sayName2.call(dave) // John

john.sayName1.apply(dave) // Dave (because 'this' is now the dave object)
john.sayName2.apply(dave) // John

john.sayName1.bind(dave)() // Dave (because 'this' is now the dave object)
john.sayName2.bind(dave)() // John

var sayNameFromWindow1 = john.sayname1
sayNameFromWindow1() // undefined (because 'this' is now the window object)

var sayNameFromWindow2 = john.sayName2
sayNameFromWindow2() // John

여기에서 주요 장점은 this는 일반 함수에 대해 변경될 수 있지만, 컨텍스트는 항상 화살표 함수에 대해 동일하게 유지된다는 것입니다. 따라서 화살표 함수를 앱의 다른 부분으로 전달하는 경우에도 컨텍스트 변경에 대해 걱정할 필요가 없습니다.

이는 특히 React 클래스 컴포넌트에서 유용할 수 있습니다. 일반 함수를 사용하는 클릭 핸들러와 같은 클래스 메소드를 정의한 다음, 해당 클릭 핸들러를 하위 컴포넌트의 prop으로 전달하면 상위 컴포넌트의 생성자에서 this도 바인드해야합니다.]

대신 화살표 함수를 사용하면, 메소드가 this값을 주위 렉시컬 컨텍스트에서 자동으로 가져오기 때문에 this를 바인딩할 필요가 없습니다.

객체나 배열에 대한 디스트럭쳐링 예시를 들 수 있나요?

디스트럭쳐링은 ES6에서 사용할 수 있는 표현식으로 객체나 배열의 값을 추출하여 다른 변수에 배치하는 간결하고 편리한 방법을 제공합니다.

// 변수 할당
const foo = ['one', 'two', 'three']

const [one, two, three] = foo

console.log(one) // "one"
console.log(two) // "two"
console.log(three) // "three"
// 변수 교환
let a = 1
let b = 3
;[a, b] = [b, a]
console.log(a) // 3
console.log(b) // 1

객체 디스트럭쳐링

//변수 할당
const o = { p: 42, q: true }
const { p, q } = o

console.log(p) // 42
console.log(q) // true